/*
 * ==================================================
 * 项目开发者：JerryStark
 * 开发者Email：4771007@qq.com
 * 开发者QQ:4771007
 * 开发范围：web，wap，android,ios,osx or win or linux 应用
 * ==================================================
 */
package Auto;

import RTPower.RTFile;
import RTPower.RTHttp;
import RTPower.RTdate;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.activation.MimetypesFileTypeMap;

/**
 * 微信上传类
 *
 * @author jerry
 */
public class WeXinUploadFile {

    /**
     * 微信文件上传host
     */
    public static String PostHost = "file.wx2.qq.com";
    /**
     * 微信文件上传接收url
     */
    public String PostUrl = "https://" + PostHost + "/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json";

    /**
     * 当前用户第几次上传的编号 默认0开始,每发一次+1
     */
    public int FileNumber = 0;

    /**
     * 表单区分标示
     */
    public String BOUNDARY;

    /**
     * 消息主体
     */
    public StringBuffer SBodyStringBuffer = new StringBuffer();

    /**
     * 一个换行符
     */
    public String OneBR = "\r\n";
    /**
     * 全局使用的http类实例
     */
    public URL HttpURL;

    public HttpURLConnection Conn;

    /**
     * 发送给那个用户的username
     */
    public String ToUserName;

    /**
     * 要上传的图片
     */
    public File UpLoadFile;

    /**
     * 文件类型
     */
    public String FileType;

    /**
     * json字符集(身份信息和上传的文件信息)
     */
    public String UploadMediaRequest;

    /**
     * 要使用的cookies
     */
    public HashMap UseCookies;

    /**
     * 初始化方法
     *
     * @param up_file 要上传的文件
     * @param toUserName 发送给哪个用户
     */
    public WeXinUploadFile(File up_file, String toUserName, String uploadmediarequest, HashMap use_cookies) {
        ToUserName = toUserName;
        UpLoadFile = up_file;
        FileType = new MimetypesFileTypeMap().getContentType(UpLoadFile);
        UploadMediaRequest = uploadmediarequest;
        UseCookies = use_cookies;

        //创建一个区分标示
        MakeBoundary();
        //初始化一个http
        try {
            HttpURL = new URL(PostUrl);
            Conn = (HttpURLConnection) HttpURL.openConnection();
        } catch (MalformedURLException ex) {
            System.err.println(ex.getMessage());
        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }

        //设置请求头
        SetHttpHead();

        //构建主体内容
        SetHttpBody();

        //测试显示已经生成的body
//        System.err.println(SBodyStringBuffer.toString());
        //把主体和图片信息加入outputStream,开始发送
    }

    /**
     * 开始发送请求
     * @return 
     */
    public String SendUpFile() {
        String result = "";

        Conn.setDoOutput(true);
        Conn.setDoInput(true);
//        Conn.setUseCaches(false);
        try {
            OutputStream outputStream = new DataOutputStream(Conn.getOutputStream());
            outputStream.write(SBodyStringBuffer.toString().getBytes("utf-8"));

            DataInputStream fileInputStream = new DataInputStream(new FileInputStream(UpLoadFile));
            byte[] bytes = new byte[1024];

            int numReadByte = 0;
            while ((numReadByte = fileInputStream.read(bytes, 0, 1024)) > 0) {
                outputStream.write(bytes, 0, numReadByte);
            }

            outputStream.write(OneBR.getBytes());
            outputStream.write((BOUNDARY + "--" + OneBR).getBytes("utf-8"));//标识请求数据写入结束
            //主体写完
            //开始发送
            outputStream.flush();

            //读取url响应
            InputStream inputs = Conn.getInputStream();
            InputStreamReader inputsr = new InputStreamReader(inputs, "utf-8");
            BufferedReader input = new BufferedReader(inputsr);
            String lineString;

            try {
                while ((lineString = input.readLine()) != null) {
                    result += lineString;
                }
            } catch (IOException ex) {
                RTFile.d_error(ex, "读取行数据出错:" + ex.getMessage());
            }

            fileInputStream.close();
            outputStream.close();
            System.err.println("成功上传:" + result);
            return result;

        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        } finally {
            UpLoadFile = null;
            if (Conn != null) {
                Conn = null;
            }
            HttpURL = null;

        }

        return result;

    }

    /**
     * 设置请求头
     */
    private void SetHttpHead() {
        try {
            Conn.setRequestMethod("POST");
        } catch (ProtocolException ex) {
            System.err.println(ex.getMessage());
        }
        // 设置通用的请求属性
        Conn.setRequestProperty("accept", "*/*");
        Conn.setRequestProperty("user-agent",
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        //设置超时时间
        Conn.setConnectTimeout(20000);//连接主机超时时间
        Conn.setReadTimeout(20000);//从主机读取数据超时时间

        Conn.setRequestProperty("Host", PostHost);
        Conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
        Conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
        Conn.setRequestProperty("Cache-Control", "no-cache");
        Conn.setRequestProperty("Connection", "Keep-Alive");
        Conn.setRequestProperty("Content-Length", Long.toString(UpLoadFile.length()));//文件总长度
        Conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);//文件总长度
        Conn.setRequestProperty("Origin", "https://wx2.qq.com");
        Conn.setRequestProperty("Pragma", "no-cache");
        Conn.setRequestProperty("Referer", "https://wx2.qq.com");
        //构建完毕后,区分符号要多加--,正式body使用的时候
        BOUNDARY = "--" + BOUNDARY;
    }

    /**
     * 构建消息主体
     */
    private void SetHttpBody() {

        //开始组装主体
        //一开始就是一个标示符号 加 换行一个
        SetAddOneBody("id", "WU_FILE_" + FileNumber);//文件id
        SetAddOneBody("name", UpLoadFile.getName());//文件名称
        SetAddOneBody("type", FileType);//文件类型
        SetAddOneBody("lastModifiedDate", RTdate.GetGMTTime(UpLoadFile.lastModified()));//文件最后修改时间
        SetAddOneBody("size", Long.toString(UpLoadFile.length()));//文件大小
        SetAddOneBody("mediatype", "pic");//媒体类型
        SetAddOneBody("uploadmediarequest", UploadMediaRequest);//json身份信息

        SetAddOneBody("webwx_data_ticket", UseCookies.get("webwx_data_ticket").toString());//json身份信息
        SetAddOneBody("pass_ticket", UseCookies.get("pass_ticket").toString());//json身份信息

        //这里单独处理upfile的消息
        SetOneFileBody();

        //最后加入结束的标识符
    }

    /**
     * 生成一个表单的区分标示
     */
    private void MakeBoundary() {
        //准备一个浏览器的随机符号,以及内容分隔符
        //最后补上4位随机
        int rand_num = new Random().nextInt(99999);
        String read_num = "" + System.currentTimeMillis() + "" + rand_num;
        BOUNDARY = "-----------------------------" + read_num;
    }

    /**
     * 增加一条设置
     * <br>这里生成的格式是:
     * <br>====================aaaaaaa
     * <br>Content-Disposition: form-data; name="add_name"
     * <br>
     * <br>add_value
     * <br>(结尾这里是个换行,下一个加入时候开始就不换行的,页就是紧接着这里)
     * <br>以上.....
     *
     * @param add_name
     * @param add_value
     */
    private void SetAddOneBody(String add_name, String add_value) {
        SBodyStringBuffer.append(BOUNDARY).append(OneBR);
        SBodyStringBuffer.append("Content-Disposition: form-data; name=\"" + add_name + "\"");
        //换行再换行
        SBodyStringBuffer.append(OneBR).append(OneBR);
        //加入值
        SBodyStringBuffer.append(add_value).append(OneBR);

    }

    /**
     * 增加一个上传文件到主体,就一个文件
     */
    private void SetOneFileBody() {
        SBodyStringBuffer.append(BOUNDARY).append(OneBR);
        SBodyStringBuffer.append("Content-Disposition: form-data; name=\"filename\"; filename=\"" + UpLoadFile.getName() + "\"");
        SBodyStringBuffer.append(OneBR);
        SBodyStringBuffer.append("Content-Type: " + FileType);
        SBodyStringBuffer.append(OneBR);
        SBodyStringBuffer.append(OneBR);
        //一下是图片的数据
    }
}
